home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / applic / ntp / kent.shar / demodes.c next >
Encoding:
C/C++ Source or Header  |  1991-09-29  |  20.4 KB  |  702 lines

  1. /* demodes.c: jl 30 April 1986: demonstrate DES in various modes */
  2.  
  3. /* this uses a version of DES that is driven directly            */
  4. /* from the NBS tables (including E) and hence is rather slow    */
  5. /* (100ms to encrypt a block on a C/70).                         */
  6. /* it is fairly compact.                                         */
  7.  
  8. /* key schedule code (from dumbksb.c) does not use the pc2 optimization */
  9. /* and outputs a key schedule as an array of longs               */
  10. /* where each long contains a 24-bit right-justified             */
  11. /* quantity, compatible with unoptimized e                       */
  12.  
  13. #ifdef BBN
  14. #  include        <style.h>
  15. #else
  16. #  define TRUE  1
  17. #  define FALSE 0
  18. #endif
  19. #include        <stdio.h>
  20. #include        <ctype.h>
  21.  
  22. /* --- some bit manipulation primitives --- */
  23.  
  24. /* g_bit -- extract bit bnum from a byte. 
  25.    As per NBS, MSB is bit 1, LSB bit 8 */
  26. int g_bit (bnum, byte)
  27. int             bnum;
  28. unsigned        byte;
  29. {
  30.   byte &= 0XFF;
  31.   return (01 & (byte >> (8 - bnum)) );
  32. }
  33.  
  34. int     gb_f28 (bnum, lval)     
  35. /* get the bnum bit from 28-bit lval */
  36. int     bnum;
  37. long    lval;
  38. {
  39.   return (01 & (lval >> (28 - bnum)) );
  40. }  
  41.  
  42.  
  43. /* --- following code and data does key schedule generation --- */
  44. #define NINPC1  28
  45. #define NINPC2  48
  46. #define PC2FRR  24      /* number of output bits from C or D */
  47. #define SUCCESS 0       /* return values from ksmake */
  48. #define FAILURE 1
  49.  
  50. int ksmake (inkey, ks)       /* Make a key schedule from key bytes in inkey */
  51.                  /* result is SUCCESS if OK, FAILURE otherwise */
  52. unsigned      inkey [8];
  53. long          ks [16] [2];
  54. {
  55.   static int pc1c [] =
  56.     { 57, 49, 41, 33, 25, 17, 9,
  57.       1, 58, 50, 42, 34, 26, 18,
  58.       10, 2, 59, 51, 43, 35, 27,
  59.       19, 11, 3, 60, 52, 44, 36 };
  60.  
  61.   static int pc1d [] =
  62.     { 63, 55, 47, 39, 31, 23, 15,
  63.       7, 62, 54, 46, 38, 30, 22,
  64.       14, 6, 61, 53, 45, 37, 29,
  65.       21, 13, 5, 28, 20, 12, 4 };
  66.  
  67.   static int shiftsked []=
  68.      { 1, 1, 2, 2, 2, 2, 2, 2,
  69.       1, 2, 2, 2, 2, 2, 2, 1 };
  70.  
  71.   static int pc2 [] =
  72.     { 14, 17, 11, 24, 1, 5,
  73.       3, 28, 15, 6, 21, 10,
  74.       23, 19, 12, 4, 26, 8,
  75.       16, 7, 27, 20, 13, 2,
  76.       41, 52, 31, 37, 47, 55,
  77.       30, 40, 51, 45, 33, 48,
  78.       44, 49, 39, 56, 34, 53,
  79.       46, 42, 50, 36, 29, 32 };
  80.  
  81.   int   i, j, parac, round, nshifts;
  82.   long  pcc, pcd;
  83.   unsigned incopy;
  84.  
  85.   /* first check parity */
  86.   for (i = 0; i < 8; i++)       /* do each byte */
  87.   {
  88.     parac = 0;
  89.     incopy = inkey [i];
  90.  
  91.     for (j = 0; j < 8; j++)     /* 8 bits in a DES byte */
  92.     {
  93.       if (incopy & 01) parac++;
  94.       incopy >>= 1;
  95.     }
  96.     if (! (parac & 01)) return (FAILURE); /* no odd parity on this byte */
  97.   }
  98.  
  99.   /* now do pc1 permutation */
  100.   pcc = pcd = 0L;
  101.   for (i = 0; i < NINPC1; i++)   /* filling all appropriate bits */
  102.   {
  103.     pcc |= (01 & g_bit (pc1c [i] % 8, (unsigned) (inkey [pc1c [i] / 8])));
  104.     pcd |= (01 & g_bit (pc1d [i] % 8, (unsigned) (inkey [pc1d [i] / 8])));
  105.     if (i != (NINPC1 - 1))       /* avoid superfluous final shift */
  106.     {
  107.       pcc <<= 1;
  108.       pcd <<= 1;
  109.     }
  110.   }
  111.  
  112.   for (round = 0; round < 16; round++)
  113.   {
  114.     for (nshifts = 0; nshifts < shiftsked [round]; nshifts++)
  115.     {
  116.       /* do appropriate number of 28-bit left rotates on pcc, pcd */
  117.       pcc <<= 1;
  118.       if (0X10000000L & pcc) pcc++;
  119.       pcc &= 0XFFFFFFFL;
  120.       pcd <<= 1;
  121.       if (0X10000000L & pcd) pcd++;
  122.       pcd &= 0XFFFFFFFL;
  123.     }
  124.  
  125.     /* Now, pcc and pcd have the values on which we can apply
  126.        pc2 and select the key bits, storing them in ks[0] and
  127.        ks[1]. The high order [ks[0]] bits all come from
  128.        pcc, and the low order from pcd. */
  129.  
  130.     ks [round] [0] = ks [round] [1] = 0;
  131.     for (i = 0; i < PC2FRR; i++)
  132.     {
  133.       ks [round] [0] |= gb_f28 (pc2 [i], pcc);
  134.       if (i != (PC2FRR - 1)) ks [round] [0] <<= 1;
  135.     }
  136.     for (i = PC2FRR; i < NINPC2; i++)
  137.     {
  138.       ks [round] [1] |= gb_f28 (pc2 [i] - NINPC1, pcd);
  139.       if (i != (NINPC2 - 1)) ks [round] [1] <<= 1;
  140.     }
  141.   }
  142.   return (SUCCESS);
  143. }
  144.  
  145. #define IP      1       /* flag to select IP */
  146. #define IPI     IP+1    /* flag to select IPI */
  147. #define ENCRYPT IPI+1   /* flag to select encryption */
  148. #define DECRYPT ENCRYPT+1       /* flag to select decryption */
  149.  
  150. /* dop -- permute 64 bits via choice of IP or IPI */
  151. dop (inar, outar, flag)
  152. long    inar [2];
  153. long    outar [2];
  154. int     flag;
  155. {
  156.   static int ip [64] =
  157.     { 58, 50, 42, 34, 26, 18, 10, 2,
  158.       60, 52, 44, 36, 28, 20, 12, 4,
  159.       62, 54, 46, 38, 30, 22, 14, 6,
  160.       64, 56, 48, 40, 32, 24, 16, 8,
  161.       57, 49, 41, 33, 25, 17, 9, 1,
  162.       59, 51, 43, 35, 27, 19, 11, 3,
  163.       61, 53, 45, 37, 29, 21, 13, 5,
  164.       63, 55, 47, 39, 31, 23, 15, 7};
  165.  
  166.   static int ipi [64] =
  167.     { 40, 8, 48, 16, 56, 24, 64, 32, 
  168.       39, 7, 47, 15, 55, 23, 63, 31,
  169.       38, 6, 46, 14, 54, 22, 62, 30,
  170.       37, 5, 45, 13, 53, 21, 61, 29,
  171.       36, 4, 44, 12, 52, 20, 60, 28,
  172.       35, 3, 43, 11, 51, 19, 59, 27,
  173.       34, 2, 42, 10, 50, 18, 58, 26,
  174.       33, 1, 41, 9, 49, 17, 57, 25};
  175.  
  176.   int i;
  177.  
  178.   outar [0] = outar [1] = 0L;
  179.   for (i = 1; i < 33; i++)
  180.   {   
  181.     outar [0] |= 01 & ((((flag == IP) ? ip[i-1] : ipi[i-1]) < 33) ? 
  182.      (inar [0] >> (32 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) : 
  183.      (inar [1] >> (64 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) );
  184.     if (i != 32) outar [0] <<= 1;
  185.   }
  186.   for (i = 33; i < 65; i++)
  187.   {   
  188.     outar [1] |= 01 & ((((flag == IP) ? ip[i-1] : ipi[i-1]) < 33) ? 
  189.      (inar [0] >> (32 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) : 
  190.      (inar [1] >> (64 - ((flag == IP) ? ip[i-1] : ipi[i-1]))) );
  191.     if (i != 64) outar [1] <<= 1;
  192.   }
  193. }
  194.  
  195. /* dodes -- encrypt or decrypt a block under key sched in ks */
  196. dodes (inar, outar, flag, ks)
  197. long    inar [2];
  198. long    outar [2];
  199. int     flag;
  200. long    ks [16] [2];
  201. {
  202. /* tables to define S boxes and P, per NBS */
  203.  
  204.   static int s_table [8] [4] [16] =
  205.     { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  206.       0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  207.       4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  208.       15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
  209.  
  210.       15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  211.       3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  212.       0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  213.       13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
  214.  
  215.       10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  216.       13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  217.       13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  218.       1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
  219.  
  220.       7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  221.       13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  222.       10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  223.       3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
  224.  
  225.       2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  226.       14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  227.       4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  228.       11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
  229.  
  230.       12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  231.       10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  232.       9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  233.       4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
  234.  
  235.       4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  236.       13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  237.       1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  238.       6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
  239.  
  240.       13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  241.       1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  242.       7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  243.       2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 };
  244.  
  245.   static int ptab [32] =
  246.     { 16, 7, 20, 21,
  247.       29, 12, 28, 17,
  248.       1, 15, 23, 26,
  249.       5, 18, 31, 10,
  250.       2, 8, 24, 14,
  251.       32, 27, 3, 9,
  252.       19, 13, 30, 6,
  253.       22, 11, 4, 25 };
  254.  
  255.   static int etab [48] = 
  256.     { 32, 1, 2, 3, 4, 5,
  257.       4, 5, 6, 7, 8, 9,
  258.       8, 9, 10, 11, 12, 13,
  259.       12, 13, 14, 15, 16, 17,
  260.       16, 17, 18, 19, 20, 21,
  261.       20, 21, 22, 23, 24, 25,
  262.       24, 25, 26, 27, 28, 29,
  263.       28, 29, 30, 31, 32, 1};
  264.  
  265.   register int round, sb, sbidx, i, j;
  266.   long expan [2];   /* receives output of E transform */
  267.   long sbout, scopy;
  268.   long oarr [2];
  269.  
  270.   dop (inar, outar, IP);
  271.  
  272.   for (round = 0; round < 16; round++)
  273.   {
  274.   /* first perform des e transformation of 32->48 bits.
  275.    accepts an input long, returns result into an array of two longs
  276.    with 24 low-order bits in each element */
  277.     expan [0] = expan [1] = 0L;
  278.     for (i = 1; i < 25; i++)
  279.     {
  280.       expan [0] |= 01 & (outar [1] >> (32 - etab[i-1]));    
  281.       if (i != 24) expan [0] <<= 1;
  282.     }
  283.     for (i = 25; i < 49; i++)
  284.     {
  285.       expan [1] |= 01 & (outar [1] >> (32 - etab[i-1]));
  286.       if (i != 48) expan [1] <<= 1;
  287.     }
  288.   /* xor expanded quantity with key schedule */
  289.     expan [0] ^= ks [(flag == ENCRYPT) ? round : 15 - round] [0];
  290.     expan [1] ^= ks [(flag == ENCRYPT) ? round : 15 - round] [1];
  291.     scopy = 0L;
  292.     for (sb = 0; sb < 8; sb++)
  293.     {  /* look up bits in s-boxes, filling a 32 bit word */
  294.       sbidx = 0X3F & ((sb < 4) ? 
  295.       (expan [0] >> (18 - (6 * sb))) : (expan [1] >> (18 - (6 * (sb-4)))) );
  296.       /* select bits per nbs spec */
  297.       i = sbidx; i &= 0X20; i >>= 4; i |= 01 & sbidx;      
  298.       j = sbidx; j &= 0X1E; j >>= 1;
  299.       scopy |= s_table [sb] [i] [j];
  300.       if (sb != 7) scopy <<= 4;
  301.     }
  302.     /* now, perform p permutation into 'sbout' */
  303.     sbout = 0L;
  304.     for (i = 1; i < 33; i++)
  305.     {
  306.       sbout |= 01 & (scopy >> (32 - ptab [i-1]));
  307.       if (i != 32) sbout <<= 1;
  308.     }
  309.  
  310.     scopy = outar [0];
  311.     outar [0] = outar [1];
  312.     outar [1] = scopy ^ sbout;
  313.   }
  314.  
  315.   /* a final swap into temp copy - let dop move into true output array */
  316.   scopy = outar [0];
  317.   oarr [0] = outar [1];
  318.   oarr [1] = scopy;
  319.   dop (oarr, outar, IPI);
  320. }
  321.  
  322. /* support routines for demodes */
  323.  
  324. /* read input bytes from stdin */
  325. int     g_inbytes (nby, buffer)     /* returns TRUE iff EOF reached */
  326. int     nby;        /* number of bytes needed at a time */
  327.             /* if insufficient, will be padded with nulls */
  328. char    buffer [];
  329. {
  330.   int   bufix;
  331.   int   getcval;
  332.  
  333.   /* init all significant bytes to null pad */
  334.   for (bufix = 0; bufix < nby; bufix++) buffer[bufix] = 0;
  335.  
  336.   for (bufix = 0; bufix < nby; bufix++)
  337.   {
  338.     getcval = getchar ();
  339.     buffer [bufix] = (char) getcval;
  340.     if (getcval == EOF)
  341.     {
  342.       buffer[bufix] = 0;        /* replace with pad */
  343.       return (TRUE);            /* indicating that EOF detected */
  344.     }
  345.   }
  346.   return (FALSE);       /* indicating no EOF detected */
  347. }
  348.  
  349. /* represent a series of bytes (conditionally) in two buffers, as
  350.    printable representation and hex representation */
  351. di_bytes (nby, inbuf, pr_buf, hx_buf)
  352. int     nby;
  353. char    inbuf [];
  354. char    pr_buf [];      /* NULL if not desired */
  355. char    hx_buf [];      /* NULL if not desired */
  356. {
  357.   int i;
  358.  
  359.   for (i = 0; i < nby; i++)
  360.   {
  361.     if (pr_buf != NULL)
  362.     {
  363.       /* Try to show as a printable character, either directly or */
  364.       /* by masking off the MSB (if the latter, prefix with '#') */
  365.       if (inbuf [i] > 0x7f)
  366.       {
  367.     if (isprint (inbuf [i] & 0x7f))
  368.       sprintf (pr_buf, "#%c", inbuf [i] & 0x7f);
  369.     else sprintf (pr_buf, "  ");
  370.       }
  371.       else
  372.       {
  373.     if (isprint (inbuf [i]))
  374.       sprintf (pr_buf, " %c", inbuf [i]);
  375.     else sprintf (pr_buf, "  ");
  376.       }
  377.       pr_buf += 2;
  378.     }
  379.     if (hx_buf != NULL)
  380.     {
  381.       sprintf (hx_buf, "%1x%1x", 0xf & (inbuf[i]>>4),0xf & inbuf [i]);
  382.       hx_buf += 2;
  383.     }
  384.   }
  385.   if (pr_buf != NULL) sprintf (pr_buf, "|");
  386.   if (hx_buf != NULL) sprintf (hx_buf, "|");
  387. }
  388.  
  389. packbtol (as_ba, as_l)   /* pack 4 bytes into a long */
  390. char    as_ba [];
  391. long    *as_l;
  392. {
  393.   long lt;
  394.  
  395.   lt = as_ba [0] & 0xff;
  396.   lt <<= 8;
  397.   lt |= as_ba [1] & 0xff;
  398.   lt <<= 8;
  399.   lt |= as_ba [2] & 0xff;
  400.   lt <<= 8;
  401.   lt |= as_ba [3] & 0xff;
  402.  
  403.   *as_l = lt;
  404. }
  405.  
  406. sprdltob (as_l, as_ba)  /* spread a long into 4 bytes */
  407. long    as_l;
  408. char    as_ba [];
  409. {
  410.   as_ba [0] = (char) ((as_l >> 24) & 0xff);
  411.   as_ba [1] = (char) ((as_l >> 16) & 0xff);
  412.   as_ba [2] = (char) ((as_l >> 8) & 0xff);
  413.   as_ba [3] = (char) (as_l & 0xff);
  414. }
  415.  
  416. lsh64 (lar, count)      /* left shift a 64-bit quantity maintained */
  417. long    lar[];          /* in a 2-element long array. Assumes that */
  418. int     count;          /* a long has at least 32 bits */
  419. {
  420.   int   i; 
  421.   long  t;
  422.  
  423.   for (i = 0; i < count; i++)
  424.   {
  425.     t = (lar [1] >> 31) & 0x1l;
  426.     lar [1] <<= 1;
  427.     lar [0] <<= 1;
  428.     lar [0] |= t;
  429.   }  
  430.   lar [0] &= 0xffffffffl;
  431.   lar [1] &= 0xffffffffl;
  432. }
  433.  
  434. rsh64 (lar, count)      /* right shift a 64-bit quantity maintained */
  435. long    lar[];          /* in a 2-element long array. Assumes that */
  436. int     count;          /* a long has at least 32 bits */
  437. {
  438.   int   i; 
  439.   long  t;
  440.  
  441.   for (i = 0; i < count; i++)
  442.   {
  443.     t = lar [0] & 0x1l;
  444.     lar [1] >>= 1;
  445.     lar [0] >>= 1;
  446.     lar [1] |= (t << 31);
  447.   }  
  448. }
  449.  
  450. rplr64 (base, modr, nbits)      /* replace rightmost nbits of base */
  451. long    base[];                 /* (64-bit qty in 2-elmt long array) */
  452. long    modr[];                 /* with corresponding bits from modr */
  453. int     nbits;
  454. {       /* Assumes longs are 32 bits or more */
  455.   long  mask;
  456.   long  lmod;   /* local copy of modr word */
  457.  
  458.   mask = (nbits >= 32) ? 0xffffffffl : ((0x1l << nbits) - 1);
  459. /*  mask = (0x1l << ((nbits > 32) ? 32 : nbits)) - 1; */
  460.   base [1] &= ~mask;    /* wipe out existing low bits */
  461.   lmod = modr [1] & mask;
  462.   base [1] |= lmod;
  463.  
  464.   nbits -= 32;
  465.   if (nbits <= 0) return;
  466.   
  467.   mask = (0x1l << nbits) - 1;
  468.   base [0] &= ~mask;
  469.   lmod = modr [0] & mask;
  470.   base [0] |= lmod;
  471. }
  472.  
  473. cpy64 (src, dest)       /* copy src 2-elmt long array to dest */
  474. long    src[];
  475. long    dest[];
  476. {
  477.   dest [0] = src [0];
  478.   dest [1] = src [1];
  479. }
  480.  
  481. #define ECB     1
  482. #define CBC     ECB+1
  483. #define OFB     CBC+1
  484. #define CFB     OFB+1
  485.  
  486. main (argc,argv)
  487. int     argc;
  488. char    *argv [];
  489. {
  490.   int   argn;
  491.   int   dmode;
  492.   int   eofyet = FALSE; /* will set to TRUE when end of input */
  493.   int   quant = 0;      /* quantum size (in bits) for selected mode */
  494.   int   flwid;          /* size to display a 64-bit chunk of pt or ct */
  495.   int   i, j;
  496.   long  iv [2], keyl [2];
  497.  
  498.   unsigned      inkey [8];
  499.   char  inkeyc [8]; 
  500.   char  inbbuf [8], otbbuf [8];
  501.   char  iprline [80], ihxline [80], ohxline [80];
  502.   long      ks [16] [2];
  503.  
  504.   long plain [2], crypt [2], cprbuf [2], cipher [2];
  505.  
  506.   /* default key and IV to NBS sample values */
  507.   keyl [0] = 0x01234567l;
  508.   keyl [1] = 0x89abcdefl;
  509.   iv [0] = 0x12345678l;
  510.   iv [1] = 0x90abcdefl;
  511.  
  512.   /* scan the command line */
  513.   for (argn = 1; argn <= argc; argn++)
  514.   {
  515.     if (seq_nocase (argv[argn], "-m")) /* mode specifier */
  516.     {  /* one string argument expected */
  517.       argn++;
  518.       if (seq_nocase (argv[argn], "ecb")) 
  519.       {
  520.         dmode = ECB; quant = 64;
  521.       }
  522.       else if (seq_nocase (argv[argn], "cbc")) 
  523.       {
  524.         dmode = CBC; quant = 64;
  525.       }
  526.       else if (seq_nocase (argv[argn], "ofb")) 
  527.       {
  528.         dmode = OFB; if (quant == 0) quant = 64; /* may be overridden */
  529.       }
  530.       else if (seq_nocase (argv[argn], "cfb")) 
  531.       {
  532.         dmode = CFB; if (quant == 0) quant = 64; /* may be overridden */
  533.       }
  534.     }
  535.     else if (seq_nocase (argv[argn], "-k"))    /* key specifier */
  536.     {  /* two long hex numerics expected */
  537.       argn++;
  538.       sscanf (argv[argn], "%lx", &keyl [0]);
  539.       argn++;
  540.       sscanf (argv[argn], "%lx", &keyl [1]);
  541.     }
  542.     else if (seq_nocase (argv[argn], "-iv"))   /* IV specifier */
  543.     {  /* two long hex numerics expected */
  544.       argn++;
  545.       sscanf (argv[argn], "%lx", &iv [0]);
  546.       argn++;
  547.       sscanf (argv[argn], "%lx", &iv [1]);
  548.     }
  549.     else if (seq_nocase (argv[argn], "-q"))     /* quantum specifier */
  550.     { /* one decimal number expected */
  551.       argn++;
  552.       sscanf (argv[argn], "%d", &quant);
  553.     }
  554.   }
  555.  
  556.   if (((dmode == ECB) || (dmode == CBC)) && (quant != 64))
  557.   {
  558.     printf ("Can't override quantum of 64 for ECB or CBC modes... aborting\n");
  559.     exit (1);
  560.   }
  561.  
  562.   /* build key schedule (outside scanner, so default works) */
  563.   sprdltob (keyl [0], & inkeyc [0]);
  564.   sprdltob (keyl [1], & inkeyc [4]);
  565.   for (i = 0; i < 8; i++) inkey [i] = (unsigned) (inkeyc [i] & 0xff);
  566.   if (ksmake (inkey, ks) != SUCCESS)
  567.   {
  568.     printf ("Bad parity on key... aborting...\n");
  569.     exit (1);
  570.   }
  571.  
  572.   printf ("Mode is ");
  573.   switch (dmode)
  574.   {
  575.     case ECB:
  576.       printf ("ECB;");
  577.       break;
  578.     case CBC:
  579.       printf ("CBC;");
  580.       break;
  581.     case OFB:
  582.       printf ("OFB;");
  583.       printf (" Quantum is %d;", quant);
  584.       break;
  585.     case CFB:
  586.       printf ("CFB;");
  587.       printf (" Quantum is %d;", quant);
  588.       break;
  589.     default:
  590.       printf ("Unknown;");
  591.       break;
  592.   }
  593.   printf (" Key is %lx %lx;", keyl [0], keyl [1]);
  594.   if (dmode != ECB) printf (" IV is %lx %lx;", iv [0], iv [1]);
  595.   printf ("\n");
  596.  
  597.   flwid = (8 * 2) + 1;      /* 8 bytes, 2 chars/byte, and a delimiter */
  598.  
  599.   while (eofyet == FALSE)       /* until EOF detected on input */
  600.   {
  601.     if (dmode == ECB)
  602.     {
  603.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  604.       {
  605.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  606.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  607.         packbtol (&inbbuf[0], &plain[0]);
  608.         packbtol (&inbbuf[4], &plain[1]);
  609.         dodes (plain, crypt, ENCRYPT, ks);
  610.         sprdltob (crypt[0], &otbbuf[0]);
  611.         sprdltob (crypt[1], &otbbuf[4]);
  612.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  613.     if (TRUE == eofyet) break;
  614.       }
  615.     }
  616.     else if (dmode == CBC)
  617.     {
  618.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  619.       {
  620.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  621.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  622.         packbtol (&inbbuf[0], &plain[0]);
  623.         packbtol (&inbbuf[4], &plain[1]);
  624.     plain [0] ^= iv [0];    /* XOR IV with input plaintext */
  625.         plain [1] ^= iv [1];
  626.         dodes (plain, crypt, ENCRYPT, ks);
  627.         sprdltob (crypt[0], &otbbuf[0]);
  628.         sprdltob (crypt[1], &otbbuf[4]);
  629.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  630.     iv [0] = crypt [0];     /* use ciphertext output as next IV */
  631.         iv [1] = crypt [1];
  632.     if (TRUE == eofyet) break;
  633.       }
  634.     }
  635.     else if (dmode == CFB)
  636.     {
  637.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  638.       /* does file read and display in 64-bit units regardless of quantum */
  639.       {
  640.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  641.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  642.         packbtol (&inbbuf[0], &plain[0]);
  643.         packbtol (&inbbuf[4], &plain[1]);
  644.     for (j = 0; j < 64; j+=quant)
  645.     {
  646.           dodes (iv, crypt, ENCRYPT, ks);
  647.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  648.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  649.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  650.       /* XOR them into DES output */
  651.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  652.       lsh64 (iv, quant);            /* shift existing IV over */
  653.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  654.       lsh64 (cipher, quant);        /* make space in cipher out array */
  655.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  656.     }
  657.         sprdltob (cipher[0], &otbbuf[0]);
  658.         sprdltob (cipher[1], &otbbuf[4]);
  659.         di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  660.     if (TRUE == eofyet) break;
  661.       }
  662.     }
  663.     else if (dmode == OFB)
  664.     {
  665.       for (i = 0; i < 4; i++)     /* 4 groups on a printable line */
  666.       {
  667.         if (TRUE == g_inbytes (8, inbbuf)) eofyet = TRUE;
  668.         di_bytes (8, inbbuf, &iprline [flwid*i], &ihxline [flwid*i]);
  669.         packbtol (&inbbuf[0], &plain[0]);
  670.         packbtol (&inbbuf[4], &plain[1]);
  671.     for (j = 0; j < 64; j+=quant)
  672.     {
  673.           dodes (iv, crypt, ENCRYPT, ks);
  674.       rsh64 (crypt, 64-quant);      /* right-align active DES output bits */
  675.       lsh64 (iv, quant);            /* shift existing IV over */
  676.       rplr64 (iv, crypt, quant);    /* replace LS IV bits with DES output */
  677.       cpy64 (plain, cprbuf);        /* copy plaintext to scratch */
  678.       rsh64 (cprbuf, 64-(quant+j)); /* right-align active plaintext bits */
  679.       /* XOR them into DES output */
  680.       crypt [0] ^= cprbuf [0];  crypt [1] ^= cprbuf [1];
  681.       lsh64 (cipher, quant);        /* make space in cipher out array */
  682.       rplr64 (cipher, crypt, quant); /* insert new output bits */
  683.     }
  684.         sprdltob (cipher[0], &otbbuf[0]);
  685.         sprdltob (cipher[1], &otbbuf[4]);
  686.     di_bytes (8, otbbuf, NULL, &ohxline [flwid*i]);
  687.         if (TRUE == eofyet) break;
  688.       }                      
  689.     }
  690.     printf ("%s\n%s\n%s\n", iprline, ihxline, ohxline);
  691.   }
  692.   printf ("\n");
  693. }
  694.  
  695. /* ------------------------------------------------------ */
  696. /* This DES software was developed by Steve Kent and John Linn */
  697. /* at BBN Communications Corporation, Cambridge, MA */
  698. /* Do not redistribute this software, or integrate with other */
  699. /* software, without preserving this notice */
  700. /* ------------------------------------------------------ */
  701.  
  702.